﻿using Newtonsoft.Json;
using Pgvector;
using SqlSugar;
using System.Data;
using System.Text;
using Yitter.IdGenerator;

namespace semantic_kernel_api.DataAccess
{
    /// <summary>
    /// 向量库帮助类
    /// </summary>
    public class VectorTool
    {

        private static string embeddingurl = DatabaseCongif.embeddingConfig.endpoint;

        private static string embeddingApikey = DatabaseCongif.embeddingConfig.apikey; 

        private static string embeddingmodel = DatabaseCongif.embeddingConfig.model;  //仅支持1024维度的模型

        private static string rerankurl = DatabaseCongif.rerankConfig.endpoint;
                              
        private static string rerankApikey = DatabaseCongif.rerankConfig.apikey;  
                            
        private static string rerankmodel = DatabaseCongif.rerankConfig.model; 


        /// <summary>
        /// 获取向量库列表
        /// </summary>
        /// <param name="title">库名称</param>
        /// <returns>返回列表Json</returns>
        public static (bool issuccess, string id) CreateVectorDb(string title)
        {
            try
            {
                VectorListEntity vectorListEntity = new VectorListEntity();
                vectorListEntity.id = YitIdHelper.NextId().ToString();
                vectorListEntity.title = title;

                var data = VectorFactory.BaseVector().Insertable(vectorListEntity).ExecuteCommand();

                return (true, vectorListEntity.id);
            }
            catch (Exception ex)
            {

                return (false,ex.Message);
            }      
        }


        /// <summary>
        /// 删除向量库列表
        /// </summary>
        /// <param name="id">库id</param>
        /// <returns>返回列表Json</returns>
        public static bool DelVectorDb(string id)
        {
            try
            {

                VectorFactory.BaseVector().Deleteable<VectorListEntity>(id).ExecuteCommand();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }

        /// <summary>
        /// 添加向量
        /// </summary>
        /// <param name="title">库名称</param>
        /// <returns>返回列表Json</returns>
        public static (bool issuccess, string id) InsertVector(string id,string dbid, string title,string content)
        {
            try
            {
                var groupid = YitIdHelper.NextId().ToString();
                
                var textlist= SplitString(content, 8000);
                foreach (var item in textlist)
                {
                    var embedding = AddAITextEmbedding(item).Result;
                    if (!embedding.isuccess)
                    {
                        return (false, id);
                    }

                    VectorEntity ent = new VectorEntity();
                    ent.id = YitIdHelper.NextId().ToString();
                    ent.groupid = groupid;
                    ent.parentid = dbid;
                    ent.title = title;
                    ent.content = item;
                    ent.embedding = new Vector(embedding.data.data[0].embedding.ToArray());

                    VectorFactory.BaseVector().Insertable(ent).ExecuteCommand();

                   
                }
                if (!string.IsNullOrWhiteSpace(id))
                {
                    VectorFactory.BaseVector().Deleteable<VectorEntity>().Where(t => t.groupid == id).ExecuteCommand();
                }

                return (true,groupid);
            }
            catch (Exception ex)
            {

                return (false, id);
            }
        }


        /// <summary>
        /// 删除向量
        /// </summary>
        /// <param name="id">向量id</param>
        /// <returns>返回列表Json</returns>
        public static bool  DelVector(string id)
        {
            try
            {
   

                VectorFactory.BaseVector().Deleteable<VectorEntity>().Where(t => t.groupid == id).ExecuteCommand();

                return true;
            }
            catch (Exception ex)
            {

                return false;
            }
        }


        /// <summary>
        /// 检索向量
        /// </summary>
        /// <param name="dbid">库id</param>
        /// <param name="content">检索内容</param>
        /// <param name="top">返回数量</param>
        /// <returns>返回列表Json</returns>
        public static (bool issuccess, List<VectorEntity> data) selectVector(string dbid,string content,int top=2, bool Rank = false)
        {
            try
            {
                
                var embedding = AddAITextEmbedding(content).Result;
                if (!embedding.isuccess)
                {
                    return (false, new List<VectorEntity>());
                }
                var embed = new Vector(embedding.data.data[0].embedding.ToArray());
                List<SugarParameter> parameters =new List<SugarParameter>();
                parameters.Add(new SugarParameter("@embedding", null)
                {
                    Value = embed,
                    DbType = System.Data.DbType.Object
                });


                var list= VectorFactory.BaseVector().Queryable<VectorEntity>().Where(t => t.parentid == dbid ).AddParameters(parameters.ToArray()).Select("*,(embedding <#> @embedding) as Similarity").OrderBy("Similarity").Take(top).ToList();
                if (Rank)
                {
                    list = ToRerank(content, list).Result;
                }
                return (true,list);
            }
            catch (Exception ex)
            {

                return (false, new List<VectorEntity>());
            }
        }



        /// <summary>
        /// 文本转换为向量
        /// </summary>
        /// <param name="text">内容</param>
        /// <returns></returns>
        private static async Task<(bool isuccess, EmbeddingResponse data)> AddAITextEmbedding(string text)
        {
            var data = new EmbeddingResponse();
            string url = $"{embeddingurl}/embeddings";

            // 请求数据
            var requestData = new
            {
                model = embeddingmodel,
                input = text,
                encoding_format = "float"
            };

            // 将请求数据序列化为 JSON
            string jsonData = JsonConvert.SerializeObject(requestData);

            // 创建 HttpClient 实例
            using HttpClient client = new HttpClient();

            // 设置请求头
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {embeddingApikey}");

            // 创建 HttpContent
            HttpContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");

            try
            {
                // 发送 POST 请求
                HttpResponseMessage response = await client.PostAsync(url, content);

                // 确保响应成功
                response.EnsureSuccessStatusCode();

                // 读取响应内容
                string responseBody = await response.Content.ReadAsStringAsync();
                data = JsonConvert.DeserializeObject<EmbeddingResponse>(responseBody);

                return (true, data);
                // 输出响应
              //  Console.WriteLine($"Usage - Prompt Tokens: {data.usage.promptTokens}");
              //  Console.WriteLine($"Usage - Completion Tokens: {data.usage.completionTokens}");
              //  Console.WriteLine($"Usage - Total Tokens: {data.usage.totalTokens}");
            }
            catch (HttpRequestException e)
            {
                return (false, new EmbeddingResponse());
                // 捕获并处理异常
               // Console.WriteLine("\nException Caught!");
               // Console.WriteLine("Message :{0} ", e.Message);
            }
        }


        private static async Task<List<VectorEntity>> ToRerank(string text, List<VectorEntity> list)
        {
            List<VectorEntity> retlist = new List<VectorEntity> { };
            var ret = await RerankEmbedding(text, list);
            if (ret.isuccess)
            {
                var rlist = ret.data.results;
                foreach (var item in rlist)
                {
                    var t = list[item.index];
                    t.Similarity = item.relevance_score;

                    retlist.Add(t);
                }
                return retlist;

            }
            else
            {

                return list;
            }






        }
        /// <summary>
        /// 重排向量
        /// </summary>
        /// <param name="text">内容</param>
        /// <returns></returns>
        private static async Task<(bool isuccess, RerankResponse data)> RerankEmbedding(string text, List<VectorEntity> list)
        {
            var data = new RerankResponse();
            string url = $"{rerankurl}/rerank";

            // 请求数据
            var requestData = new
            {
                model = rerankmodel,
                query = text,
                documents = list.Select(t => t.content).ToList(),
                top_n = list.Count,
                return_documents = false,
                max_chunks_per_doc = 1024,
                overlap_tokens = 80
            };

            // 将请求数据序列化为 JSON
            string jsonData = JsonConvert.SerializeObject(requestData);

            // 创建 HttpClient 实例
            using HttpClient client = new HttpClient();

            // 设置请求头
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {rerankApikey}");

            // 创建 HttpContent
            HttpContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");

            try
            {
                // 发送 POST 请求
                HttpResponseMessage response = await client.PostAsync(url, content);

                // 确保响应成功
                response.EnsureSuccessStatusCode();

                // 读取响应内容
                string responseBody = await response.Content.ReadAsStringAsync();
                data = JsonConvert.DeserializeObject<RerankResponse>(responseBody);

                return (true, data);
                // 输出响应
                //  Console.WriteLine($"Usage - Prompt Tokens: {data.usage.promptTokens}");
                //  Console.WriteLine($"Usage - Completion Tokens: {data.usage.completionTokens}");
                //  Console.WriteLine($"Usage - Total Tokens: {data.usage.totalTokens}");
            }
            catch (HttpRequestException e)
            {
                return (false, data);
                // 捕获并处理异常
                // Console.WriteLine("\nException Caught!");
                // Console.WriteLine("Message :{0} ", e.Message);
            }
        }


        public static List<string> SplitString(string input, int chunkSize=8000)
        {
            List<string> result = new List<string>();
            for (int i = 0; i < input.Length; i += chunkSize)
            {
                result.Add(input.Substring(i, Math.Min(chunkSize, input.Length - i)));
            }
            return result;
        }
    }
}
public class EmbeddingResponse
{
    public string model { get; set; }
    public List<EmbeddingData> data { get; set; }
    public Usage usage { get; set; }
}

public class EmbeddingData
{
    public string Object { get; set; }
    public List<float> embedding { get; set; }
    public int index { get; set; }
}

public class RerankResponse
{
    public string id { get; set; }
    public List<Rerankresults> results { get; set; }
}


public class Rerankresults
{
    public int index { get; set; }
    public double relevance_score { get; set; }

}


public class Usage
{
    public int promptTokens { get; set; }
    public int completionTokens { get; set; }
    public int totalTokens { get; set; }
}


public class DataInfo
{
    public string id { get; set; }
    public string title { get; set; }
    public double Similarity { get; set; }
    public string text { get; set; }


}